package edu.gduf.shiro;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;


@Configuration
public class shiroConfig {

    /**
     * 配置shiro的安全管理器
     * @param authRealm
     * @return
     */
    @Bean
    public SecurityManager securityManager(Realm authRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置一个Realm，这个Realm是最终用于完成认证号和授权操作的具体对象
        securityManager.setRealm(authRealm);
        return securityManager;
    }

    /**
     * 配置自定义Realm,用于登陆授权
     * @return
     */
    @Bean
    public Realm authRealm(){
        authRealm realm = new authRealm();
        return realm;
    }

    /**
     * 配置基本的过滤规则
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        // 创建Shiro的拦截器，用于拦截用户请求
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
//        Map<String, Filter> filters = shiroFilter.getFilters();
//        filters.put("authc",new CustomFormAuthenticationFilter());
        // 设置Shiro的安全管理，设置管理的同时也会指定某个Realm，用来完成我们权限的分配
        shiroFilter.setSecurityManager(securityManager);
        // 用于设置一个登陆的请求地址，这个地址可以是一个html或者jsp访问路径，也可以是一个控制器的路径
        // 作用是用于通知Shiro我们可以使用这里路径转向到登陆页面，Shiro判断用户没有登陆时会转到该路径
        shiroFilter.setLoginUrl("/login");
        // 登陆成功后转向页面
        shiroFilter.setSuccessUrl("/success");
        // 提示没有权限的页面
        shiroFilter.setUnauthorizedUrl("/login");

        // 定义一个Map集合，这个Map集合中存放的数据全部都是规则，用于设置通知Shiro什么样的请求可以访问什么样的请求不可以访问
        LinkedHashMap<String,String> filterChain = new LinkedHashMap<String,String>();
        /**
         *   可以从数据库中读取出来）
         *   或者在控制器中加入Shiro的注解
         *    /admin/** 表示一个请求名字的通配符
         *    authc 表示这个请求需要进行认证
         *    ** 表示任意子孙路径 *表示任意的一个路径 ?表示任意一个字符
         *    map.put("/admin/**,"authc")
         *    map.put("/user/**,"authc")
         *    map.put("/**","authc")
         */
        filterChain.put("/login","anon");
        filterChain.put("/user/update","authc");
        filterChain.put("/user/face","authc");
        filterChain.put("/user/updatephoto","authc");
        filterChain.put("/user/viewloginlog","authc");
        filterChain.put("/user/viewrelease","authc");
        filterChain.put("/user/chanagepassword","authc");
        filterChain.put("/message/list","authc");
        filterChain.put("/message/send","authc");
        filterChain.put("/message/viewdetail","authc");
        filterChain.put("/logout","logout");
        shiroFilter.setFilterChainDefinitionMap(filterChain);
        return shiroFilter;

    }

    /**
     * 开启注解配置
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    /**
     * 开启AOP的注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
